﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Web.Models;
using System.Data.Entity;
using Web.CustomExceptions;

namespace Web.Repositories
{
    public class CategoriaRepository
    {
        protected HoteluchoContext Db { get; set; }

        public CategoriaRepository()
        {
            Db = HoteluchoContext.Instance;
        }

        public void AltaCategoria(Categoria nuevaCategoria)
        {
            Db.Categorias.Add(nuevaCategoria);
            Db.SaveChanges();
        }

        public void BajaCategoria(Categoria remover)
        {
            if (TieneReservasActivas(remover))
            {
                throw new ReservaActivaException("La categoria que esta tratando de eliminar tiene reservas activas");
            }
            try
            {
                List<Habitacion> habitacionesBaja = new List<Habitacion>();
                foreach (var habitacion in remover.Habitaciones)
                {
                    habitacion.NombreCategoria = "";
                    //habitacionesBaja.Add(habitacion);
                }
                remover.Habitaciones.Clear();
                //foreach (var habitacionBaja in habitacionesBaja)
                //{
                //    Db.Habitaciones.Remove(habitacionBaja);
                //}
                Db.Categorias.Remove(remover);
                Db.SaveChanges();
            }
            catch (Exception Ex)
            {
                throw;
            }
        }

        private void EliminarHabitaciones()
        {
            throw new NotImplementedException();
        }

        private void EliminarReservasAntiguas()
        {
            throw new NotImplementedException();
        }

        private bool TieneReservasActivas(Categoria categoria)
        {
            var reservas = Db.Reservas.Where(x => x.Categoria.IdCategoria == categoria.IdCategoria).ToList();
            bool tieneActivas = false;
            foreach (var reserva in reservas)
            {
                if (reserva.FechaEgreso >= DateTime.Now)
                {
                    tieneActivas = true;
                    break;
                }
            }
            return tieneActivas;
        }

        /// <summary>
        /// Busca una categoria en la base de datos.
        /// </summary>
        /// <param name="idCategoria">id de la categoria a buscar</param>
        /// <returns>Devuelve la categoria que satisfaga la condicion</returns>
        public Categoria GetCategoria(int idCategoria)
        {
            return Db.Categorias.Find(idCategoria);
        }

        /// <summary>
        /// Busca la categoria en la que se encuentra una habitacion.
        /// </summary>
        /// <param name="idHabitacion"></param>
        /// <returns></returns>
        public Categoria GetCategoriaPorHabitacion(int idHabitacion)
        {
            if (Db.Categorias.Count() > 0)
            {
                return Db.Categorias.FirstOrDefault(x => x.Habitaciones.Any(y => y.IdHabitacion == idHabitacion));
            }
            //If we got this far, something went wrong;
            return null;
        }

        public List<Categoria> GetAll()
        {
            return Db.Categorias.ToList();
        }

        public List<Categoria> Buscar(string nombre)
        {
            return Db.Categorias.Where(x => x.Nombre.ToLower().Contains(nombre.ToLower())).ToList();
        }

        public void Save()
        {
            Db.SaveChanges();
        }

        //public void ModificarCategoria(Categoria modificar)
        //{
        //    Db.Categorias.Find(modificar.IdCategoria) = modificar;
        //    Db.SaveChanges();
        //}

        public List<Categoria> getCategoriasDisponiblesEnRango(DateTime fechaIngreso, DateTime fechaEgreso)
        {
            Dictionary<Categoria, int> categoriasReservadas = new Dictionary<Categoria, int>();
            List<Categoria> result = GetAll();

            ReservaRepository reservaRepository = new ReservaRepository();

            var reservas = reservaRepository.GetReservasEnRango(fechaIngreso, fechaEgreso);
            if (reservas.Count == 0)
                return Db.Categorias.ToList();

            foreach (Reserva reserva in reservas)
            {
                if (reserva.Categoria == null)
                    continue;
                if (categoriasReservadas.ContainsKey(reserva.Categoria))
                {
                    categoriasReservadas[reserva.Categoria]++;
                }
                else
                {
                    categoriasReservadas.Add(reserva.Categoria, 1);
                }
            }


            foreach (var categoria in categoriasReservadas)
            {
                if (categoria.Value >= Db.Categorias.Find(categoria.Key.IdCategoria).Habitaciones.Count)
                {
                    result.Remove(categoria.Key);
                }
            }

            return result;
        }
    }
}
